package com.tiancheng.trade.settlement.service.settlement.impl;

import com.tiancheng.trade.settlement.enums.PaymentBillStatusEnum;
import com.tiancheng.trade.settlement.exception.BusinessException;
import com.tiancheng.trade.settlement.mapper.settlement.*;
import com.tiancheng.trade.settlement.model.settlement.PaymentOrderBank;
import com.tiancheng.trade.settlement.model.settlement.PaymentOrderFinish;
import com.tiancheng.trade.settlement.service.settlement.IReconciliationService;
import com.tiancheng.trade.settlement.util.JacksonJsonUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @Auther: liudong
 * @Date: 2024/4/10 16:07
 * @Param ${tags}
 * @Description:
 */
@Service
@Slf4j
public class ReconciliationServiceImpl implements IReconciliationService {
    @Autowired
    PaymentOrderMapper paymentOrderMapper;
    @Autowired
    PaymentOrderBankMapper bankMapper;
    @Autowired
    PaymentBillMapper paymentBillMapper;
    @Autowired
    PaymentOrderBankDetailMapper paymentOrderBankDetailMapper;
    @Autowired
    PaymentOrderFinishMapper finishMapper;
    @Resource
    private JacksonJsonUtil jacksonJsonUtil;


    @Override
    public List<PaymentOrderBank> getBankCheckOrders() throws BusinessException {
        return bankMapper.getBankCheckOrders();
    }

    /**
     * 查询正确对账数据
     *
     * @param flowIds
     * @return
     */
    @Override
    public List<PaymentOrderFinish> getFinishBankOrders(List<String> flowIds) throws BusinessException {
        return finishMapper.getFinishBankOrders(flowIds);
    }

    /**
     * 获取对账异常数据
     *
     * @param flowIds
     * @return
     */
    @Override
    public List<PaymentOrderFinish> getErrorBankOrders(List<String> flowIds) throws BusinessException {
        return finishMapper.getErrorBankOrders(flowIds);
    }


    @Transactional
    @Override
    public void batchSavePaymentOrders(List<PaymentOrderFinish> orderFinishes, List<String> orderIds) throws BusinessException {
        int status = finishMapper.batchSaveFinishOrders(orderFinishes);
        if (status > 0) {
            bankMapper.updateOrderBankStatus(orderIds);
            paymentOrderMapper.updateOrderStatus(orderIds);
            paymentBillMapper.updateBillStatus(orderIds);
            paymentOrderBankDetailMapper.updateBankDetailStatus(orderIds);
        }
    }

    /**
     * 已完成对账表获取异常数据，flow_Id为空的数据
     *
     * @return
     */
    @Override
    public List<PaymentOrderFinish> getUnusualBankOrders() throws BusinessException {
        return finishMapper.getUnusualBankOrders();
    }

    /**
     * 银行侧为空时，查询对账中心待对账订单是否有待对账数据，记录数据未匹配异常
     *
     * @return
     */
    @Override
    public List<PaymentOrderFinish> getUnusualOrders() throws BusinessException {
        return finishMapper.getUnusualOrders();
    }

    /**
     * 功能描述: 流水对账，银行侧有数据与中心侧进行对账
     *
     * @param:
     * @return:
     * @auther: LiuDong
     * @date: 18:39 2024/4/20
     */
    @Override
    public List<PaymentOrderFinish> bankReconciliation(List<String> orderIds) throws BusinessException {
        List<PaymentOrderFinish> finishBankOrders = new ArrayList<>();
        //根据flowId查询对账中心数据，流水和金额都对应上的
        if (!orderIds.isEmpty()) {
            //这里是对交易类型为支付的
            finishBankOrders = finishMapper.getFinishBankOrders(orderIds);
            //获取剩余的对账数据,包含退款的和对账失败的
            List<String> refundIds = rtnBankOrderIds(finishBankOrders, orderIds);
            //由于退款要对的字段与支付不一样，所以分开对
            List<PaymentOrderFinish> refundOrders = finishMapper.getFinishRefundBankOrders(refundIds);
            if (null != refundOrders && !refundOrders.isEmpty()) {
                finishBankOrders.addAll(refundOrders);
            }
            //设置对账状态为正常
            finishBankOrders.stream().forEach(orderFinish -> orderFinish
                    .setReconciliationStatus(PaymentBillStatusEnum.SUCCESS.getCode()));
        }
        //获取对账失败的流水flowId
        List<String> errorOrderIds = rtnBankOrderIds(finishBankOrders, orderIds);
        //对账异常的数据集合
        if (!errorOrderIds.isEmpty()) {
            List<PaymentOrderFinish> errorBankOrders = finishMapper.getErrorBankOrders(errorOrderIds);
            errorBankOrders.stream().filter(orderFinish -> !StringUtils.isEmpty(orderFinish.getFlowId())).forEach(orderFinish -> orderFinish
                    .setReconciliationStatus(PaymentBillStatusEnum.ABNORMAL.getCode()));//数据异常
            errorBankOrders.stream().filter(orderFinish -> StringUtils.isEmpty(orderFinish.getFlowId())).forEach(orderFinish -> orderFinish
                    .setReconciliationStatus(PaymentBillStatusEnum.NO_MATCH.getCode()));//订单未匹配上flowId为空说明平台无数据
            if (!errorBankOrders.isEmpty()) {
                finishBankOrders.addAll(errorBankOrders);
            }
        }
        return finishBankOrders;
    }


    private List<String> rtnBankOrderIds(List<PaymentOrderFinish> finishBankOrders, List<String> orderIds) {
        //对账成功流水
        List<String> finishorderIds = finishBankOrders.stream().map(PaymentOrderFinish::getPayChannelOrderid).collect(Collectors.toList());
        //获取对账失败的流水flowId
        List<String> ids = orderIds.stream().filter(item -> !finishorderIds.contains(item)).collect(Collectors.toList());
        return ids;
    }

    /**
     * 功能描述: 中心侧有数据，银行侧无数据，记录异常订单（数据未匹配）
     *
     * @param:
     * @return:
     * @auther: LiuDong
     * @date: 10:10 2024/4/21
     */
    @Override
    public void settlementReconciliation() throws BusinessException {
        //查询中心侧是否有数据，如果有数据标记异常订单
        log.info("定时对账 银行侧数据为空，查询中心侧是否有待对账数据");
        List<PaymentOrderFinish> finishBankOrders = this.getUnusualOrders();
        finishBankOrders.stream().forEach(orderFinish -> orderFinish.setReconciliationStatus(PaymentBillStatusEnum.NO_MATCH.getCode()));
        log.info("定时对账 银行侧数据为空，中心方侧对账数据:{}", jacksonJsonUtil.toJson(finishBankOrders));
        // 异常订单flowId
        List<String> unids = finishBankOrders.stream().map(PaymentOrderFinish::getPayChannelOrderid).collect(Collectors.toList());
        if (unids.size() > 0) {
            finishBankOrders.stream().forEach(orderFinish -> orderFinish.setReconciliationDate(LocalDate.now()));
            //批量保存异常订单、更新待对账表状态
            this.batchSavePaymentOrders(finishBankOrders, unids);
        }
    }
}
